#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#define HXD019_NODE "/dev/ctrl"
#define MAX_SIZE 255
char buff[MAX_SIZE];
unsigned char learn_cmd_110[] = {0x30, 0x10, 0x40};
unsigned char learn_cmd_230[] = {0x30, 0x20, 0x50};
char data1[] = {0x30, 0x03, 0x75, 0xEF, 0x00, 0x34, 0x34, 0x00, 0x4F, 0x00, 0x26, 0x00, 0x17, 0x00, 0x44, 0x00, 0x16, 0x00, 0x24, 0x00, 0x38, 0x00, 0x53, 0x00, 0x18, 0x00, 0x24, 0x00, 0x58, 0x00, 0x44, 0x00, 0x38, 0x00, 0x43, 0x00, 0x57, 0x00, 0x01, 0x23, 0x45, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5c};


static void do_send(int n);

/* ================================= */
static void sig_handler(int signo)
{
	switch(signo){
	case SIGALRM:
		do_send(1);
		break;
	}
}


/* ===================================== */



/**
 * 向指定文件中指定的内容
 * @param  path [文件路径]
 * @param  buf  [内容]
 * @param  n    [内容字节数]
 * @return      [实际写入的字节数]
 */
static int write_file(const char *path, char *buf, int n)
{
	int fd;
	int ret;
	if((fd=open(path, O_WRONLY))<0){
		printf("open %s failed, msg=%s\n", path, strerror(errno));
		return -1;
	}
	do {
		ret = write(fd, buf, n);
	}while(ret == EAGAIN);
	if(ret < 0){
		printf("write %s for WRITE failed, msg=%s\n", path, strerror(errno));
	}else if(ret < n){
		printf("write expect %d, get %d\n", n, ret);
	}
	close(fd);
	return ret;
}

/**
 * 从指定文件中读取指定的内容
 * @param  path [文件路径]
 * @param  buf  [存放内容的缓冲区]
 * @param  n    [缓冲区大小]
 * @return      [实际读入的字节数]
 */
static int read_file(const char *path, char *buf, int n)
{
	int fd;
	int ret;
	if((fd=open(path, O_RDONLY))<0){
		printf("open %s for READ failed, msg=%s\n", path, strerror(errno));
		return -1;
	}
	do {
		ret = read(fd, buf, n);
	}while(ret == EAGAIN);
	if(ret < 0){
		printf("read %s failed, msg=%s\n", path, strerror(errno));
	}else if(ret < n){
		printf("read expect %d, get %d\n", n, ret);
	}
	close(fd);
	return ret;
}

/**
 *  用进进制的方式打印内容
 * @param buf 缓冲区
 * @param count 要显示的字符个数
 * @param tip 提示信息
 */
static void hex_dump(char *buf, int count, const char *tip)
{
	char line[256];
	int i, j, n;
	memset(line, 0, sizeof(line));
	printf("%s: count=%d\n", tip, count);
	for(i=0; i<count; i+=16){
		n = 0;
		for(j=0; j<16 && i+j<count; j++){
			n += snprintf(line+n, 256, "%02x ", buf[i+j] & 0xff);
		}
		printf("%04x: %s\n", i, line);
	}
}

static void do_send(int n)
{
	int ret = 0;
	printf("%s n=%d\n", __func__, n);
	ret = write_file(HXD019_NODE, data1, sizeof(data1));
//	hex_dump(data1, ret, "do_send");
	printf("%s ret=%d, \n", __func__, ret);
}

static void wrap_send(int n)
{
	struct itimerval it;
	it.it_interval.tv_sec = 0; 
	it.it_interval.tv_usec = 1000*300;  // 300 ms
	it.it_value = it.it_interval;
	setitimer(ITIMER_REAL, &it, NULL);  
	while(1){
		sleep(60*60);
	}
}
/**
 * 接收红数据，
 * @param kind 0 接收110字节，1 接收230字节
 */
static void do_recv(int kind)
{
	int ret = 0;
	ret = write_file(HXD019_NODE, learn_cmd_230, sizeof(learn_cmd_230));
	hex_dump(learn_cmd_230, sizeof(learn_cmd_230), "do_recv");
	ret = read_file(HXD019_NODE, buff, 230);
	hex_dump(buff, ret, "do_recv");
	printf("%s ret=%d, \n", __func__, ret);
}




static int do_read2(void)
{
	int fd;
	int ret;
	int n = MAX_SIZE;
	struct timeval tv, tv1;
	if((fd=open(HXD019_NODE, O_RDONLY))<0){
		printf("open %s for READ failed, msg=%s\n", HXD019_NODE, strerror(errno));
		return -1;
	}
	while(1){

    	gettimeofday(&tv, NULL);
		do {
			ret = read(fd, buff, n);
		}while(ret == EAGAIN);
		if(ret < 0){
			printf("read %s failed, msg=%s\n", HXD019_NODE, strerror(errno));
			break;
		}else if(ret < n){
			printf("read expect %d, get %d\n", n, ret);
		}	
	    gettimeofday(&tv1, NULL);

    	printf("Read cost : %ld\n", ((tv1.tv_sec-tv.tv_sec) *1000 + (tv1.tv_usec-tv.tv_usec )/1000));
		hex_dump(buff, ret, "do_recv");	
	}

	close(fd);
	return ret;	
}

static void usage(void)
{
	printf("Usage: hx019d -r | -s n\n");
	printf(" -r receive operation\n");
	printf(" -s n  send operation, n data set to send \n");
}

int main(int argc, char *argv[])
{
	int ch;
	int n;

	if(signal(SIGALRM,sig_handler)==SIG_ERR){
		printf("Unable to create handler for SIGALRM\n");
		exit(0);
	}
	while ((ch = getopt(argc, argv, "rs:")) != -1){
		switch(ch){
		case 'r':
			do_read2();
			break;
		case 's':
			wrap_send(atoi(optarg));
			break;
		default:
			usage();
			break;
		}
	}
	return 0;
}
